/* Class PWF.Widget
 * 
 * Super class for all Widgets 
 * Uses the mixin AjaxContentLoader to load Widget template code
 * 
 * @author David Lindkvist (david.lindkvist@shapeshift.se
 */

PWF.create('PWF.Widget', 
			PWF.mixin.DOMUtils,
			PWF.mixin.ScriptPath,
			PWF.mixin.AjaxContentLoader, 
			PWF.mixin.LoadingAnimation,
{
	/***************************************************************************************/
	// CONSTRUCTOR
	/***************************************************************************************/
	initialize: function(containerId) 
	{	
		Log.info('creating instance of '+this.getName());
		
		/*************************************************************************/
		// private properties - don't override!
		/*************************************************************************/
		this.containerId = containerId;
		this.container = $(containerId);
		this.baseName = 'pwf-'+PWF.version;
	
		/*************************************************************************
		// protected properties - feel free to override in sub class
		/*************************************************************************/		
		this.coreCSS = 'loading.css';
		this.loadingImage = 'loading.gif';
		this.loadingStyleClass = 'widgetLoading';
		this.loadErrorStyleClass = 'widgetLoadError';
		this.templateHtml = PWF.defaultHtmlTemplate;
		this.templateCSS = PWF.defaultCssTemplate;	
		this.width == undefined;
		this.height == undefined;

		//default messages
		this.msgLoadError = 'Nätverksproblem. Modulen kunde ej laddas.';
		this.msgLoadErrorRetry = 'Försök igen';

		//load overrided properties in subClass
		this.init();
	
		//continue loading widget
		this.loadWidget();
	},
	
	
	/***************************************************************************************/
	// PRIVATE METHODS
	/***************************************************************************************/
	getLoadingImageUrl: function() 
	{
		return this.getScriptPath(this.baseName) + this.loadingImage;
	},
	
	loadWidget: function() 
	{			
		Log.profile(this.getName()+' - load widget');
		
		//load core CSS
		var coreCSSUrl = this.getScriptPath(this.baseName) + this.coreCSS;
		this.loadStyleSheet(coreCSSUrl);
		
		//load CSS template for widget
		var templateCSSUrl = this.getTemplateUrl(this.templateCSS);
		this.loadStyleSheet(templateCSSUrl);
		
		//load HTML template for widget
		this.loadTemplate();
	},
	
	/* this overrides onLoadInit function in PWF.mixin.AjaxContentLoader */
	onLoadInit: function() 
	{		
		//add standard loading style
		this.container.addClassName(this.loadingStyleClass);

		//set widget size
		this.adjustWidgetSize();

		//show loading animation
		this.showLoadingAnimation();
	},
	
	/* this overrides onLoadSuccess function in PWF.mixin.AjaxContentLoader */
	onLoadSuccess: function() 
	{
		Log.info(this.getName()+' - template file loaded OK');
		
		//hide loaded html and add fade in effect
		$(this.containerId).firstDescendant().hide();
		new Effect.Appear($(this.containerId).firstDescendant(), {duration: 0.3});
	
		//call subclass specific widget behaviour
		this.widgetLoaded();

		//remove loading style class
		this.container.removeClassName(this.loadingStyleClass);
		
		Log.profile(this.getName()+' - load widget');
	},
	
	/* this overrides onLoadError function in PWF.mixin.AjaxContentLoader */
	onLoadError: function(request, exception) 
	{	
		Log.error(this.getName()+' - load widget failed: '+exception);
		
		//remove loading style class & animation
		this.container.removeClassName(this.loadingStyleClass);
		this.hideLoadingAnimation();

		//add error message & error style
		var pErrorMsg = new Element('p').update(this.msgLoadError);
		this.container.update(pErrorMsg);
		this.container.addClassName(this.loadErrorStyleClass);

		//add retry link
		var retryLink = new Element('a', {'href': '#'}).update(this.msgLoadErrorRetry);
		retryLink.observe('click', this.reloadListener.bindAsEventListener(this));
		var pRetry = new Element('p').update(retryLink);
		this.container.insert(pRetry);
	},	
	
	reloadListener: function(/*Object*/e) 
	{
		Log.info(this.getName()+' - user retrying load of template');
		
		//clear widget contents (incase of error)
		this.container.update('');

		//remove all styleclasses
		this.container.classNames().each(function(n) {
			container.removeClassName(n);
		});

		// reload widget
		this.loadWidget();
	},
	
	
	/***************************************************************************************/
	// ABSTRACT METHODS
	/***************************************************************************************/
	
	/** Override this method in sub class to implement widget behaviour */
	widgetLoaded: function() 
	{
		Log.warn(this.getName()+' - method widgetLoaded is not implemented');
		throw "method widgetLoaded must be implemented in subclass!";
	},
	
	
	/***************************************************************************************/
	// OVERRIDE RECOMENDED
	/***************************************************************************************/
	init: function() 
	{		
		// implement in subclass to override default properties or declare private properties
	},
	
	
	/***************************************************************************************/
	// PROTECTED METHODS
	/***************************************************************************************/

	/** Set container style to this.width and/or this.height */
	adjustWidgetSize: function()
	{	
		if(this.width !== undefined)
		{
			this.container.setStyle({
				width: this.width+'px'
			});	
		}
		
		if(this.height !== undefined)
		{
			this.container.setStyle({
				height: this.height+'px'
			});
		}
	},
	
	/**	Load a widget template and call the appropriate callback when loaded 
	 *	If no loadCallback is specified, widgetLoaded() will be used
	 */
	loadTemplate: function(/*String*/templateName, /*function ptr*/loadCallback) 
	{	
		// use custom template name if provided
		if(templateName === undefined)
			templateName = this.templateHtml;
		
		// use custom loadBehaviour function if provided
		if(loadCallback !== undefined)
			this.widgetLoaded = loadCallback;
			
		//get url to this template
		var templateUrl = this.getTemplateUrl(templateName);
		
		//log debug
		Log.debug(this.getName()+' - loadTemplate('+templateName+'): url='+templateUrl);
		
		// load template using PWF.mixin.AjaxContentLoader
		this.loadContent(this.container.id, templateUrl);
	},
	
	/** Finds the template element with the specified id
	 *   
	 *  NOTE: It is recommended to always use this method to find template elements.
	 *  	  The elment's id is replaced with a unique id in case this 
	 *        widget is included more than once on a single page
	 */ 
	getElement: function(/*String*/elementId)
	{
		//grab element
		var element = $(elementId);
	
		if(!element)
		{
			Log.warn(this.getName+' - getElement('+elementId+'): element does not exist');
			return null;
		}
		
		//generate unique ID for this element incase we have
		//multiple instances of this widget on the same page
		element.id = this.containerId + '_' + element.id;	

		return element;
	},
	
	getWidgetUrl: function() 
	{
		return this.getScriptPath(this.getName());
	},
	
	getTemplateUrl: function(/*String*/templateName) 
	{
		return this.getWidgetUrl() + templateName;
	},
	
	getViewUrl: function(/*String*/viewName)
	{
		return this.getWidgetUrl() + '../../views/' + viewName;
	},
	
	/** Redirect browser to a new view in this module 
	 *	@param viewName the full fileName of this view 
	 */
	redirectToView: function(/*String*/viewName)
	{
		var redirectUrl = this.getViewUrl(viewName);
		this.redirectToUrl(redirectUrl);
	},
	redirectToUrl: function(/*String*/redirectUrl)
	{
		window.location = redirectUrl;
	}
});

